package cool.webstudy.async.configuration;

import lombok.Getter;
import org.apache.commons.lang3.StringUtils;
import org.apache.http.HttpHost;
import org.apache.http.auth.AuthScope;
import org.apache.http.auth.UsernamePasswordCredentials;
import org.apache.http.client.CredentialsProvider;
import org.apache.http.conn.ssl.NoopHostnameVerifier;
import org.apache.http.impl.client.BasicCredentialsProvider;
import org.elasticsearch.client.RestClient;
import org.elasticsearch.client.RestClientBuilder;
import org.elasticsearch.client.RestHighLevelClient;
import org.elasticsearch.core.CheckedConsumer;
import org.elasticsearch.xcontent.NamedXContentRegistry;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

import javax.net.ssl.SSLContext;
import javax.net.ssl.TrustManager;
import javax.net.ssl.X509TrustManager;
import java.io.IOException;
import java.security.KeyManagementException;
import java.security.NoSuchAlgorithmException;
import java.security.SecureRandom;
import java.security.cert.X509Certificate;
import java.util.List;

/**
 * @author 莫振双
 * @date 2024/8/1 16:14
 * @description:
 */
@Configuration
public class ElasticsearchConfig {
    @Value("${spring.elasticsearch.scheme:http}")
    private String scheme;
    @Value("${spring.elasticsearch.host:127.0.0.1}")
    private String host;
    @Value("${spring.elasticsearch.port:9200}")
    private String port;
    @Value("${spring.elasticsearch.username:}")
    private String username;
    @Value("${spring.elasticsearch.password:}")
    private String password;

    @Bean
    public RestHighLevelClient restHighLevelClient() throws NoSuchAlgorithmException, KeyManagementException {
        // 创建SSL上下文以忽略证书
        SSLContext sslContext = SSLContext.getInstance("TLSv1.2");
        sslContext.init(null, new TrustManager[]{new X509TrustManager() {
            public void checkClientTrusted(X509Certificate[] chain, String authType) {
            }

            public void checkServerTrusted(X509Certificate[] chain, String authType) {
            }

            public X509Certificate[] getAcceptedIssuers() {
                return new X509Certificate[]{};
            }
        }}, new SecureRandom());
        CustomRestHighLevelClient customRestHighLevelClient;
        if (StringUtils.isNotEmpty(this.username) && StringUtils.isNotEmpty(this.password)) {
            // 使用 CredentialsProvider 对象登陆
            CredentialsProvider credentialsProvider = new BasicCredentialsProvider();
            credentialsProvider.setCredentials(AuthScope.ANY, new UsernamePasswordCredentials(this.username, this.password));
            HttpHost http = new HttpHost(host, Integer.parseInt(port), scheme);
            customRestHighLevelClient = new CustomRestHighLevelClient(RestClient.builder(http)
                    .setHttpClientConfigCallback(httpAsyncClientBuilder -> httpAsyncClientBuilder
                            //配置绕过SSL证书验证
                            .setSSLContext(sslContext).setSSLHostnameVerifier(NoopHostnameVerifier.INSTANCE)
                            .setDefaultCredentialsProvider(credentialsProvider)));
            customRestHighLevelClient.ip = host;
            customRestHighLevelClient.port = Integer.parseInt(port);
            customRestHighLevelClient.username = this.username;
            customRestHighLevelClient.password = this.password;
            customRestHighLevelClient.needAuth = Boolean.TRUE;
        } else {
            customRestHighLevelClient = new CustomRestHighLevelClient(RestClient.builder(new HttpHost(host, Integer.parseInt(port), "http")));
        }
        return customRestHighLevelClient;
    }

    public static class CustomRestHighLevelClient extends RestHighLevelClient {
        @Getter
        private String username;
        @Getter
        private String password;
        @Getter
        private String ip;
        @Getter
        private int port;
        @Getter
        private boolean needAuth;

        public CustomRestHighLevelClient(RestClientBuilder restClientBuilder) {
            super(restClientBuilder);
        }

        protected CustomRestHighLevelClient(RestClientBuilder restClientBuilder, List<NamedXContentRegistry.Entry> namedXContentEntries) {
            super(restClientBuilder, namedXContentEntries);
        }

        protected CustomRestHighLevelClient(RestClient restClient, CheckedConsumer<RestClient, IOException> doClose, List<NamedXContentRegistry.Entry> namedXContentEntries) {
            super(restClient, doClose, namedXContentEntries);
        }
    }
}
